import tkinter as tk
import numpy as np
from tkinter.filedialog import askopenfile
from PIL import Image
import math
import os
import time
import tkinter.messagebox
from numba import jit
import cv2

raw_file_pix=None
fft_file_dir=""
fft_file_pix=None
ifft_file_pix=None
cur_pix=None
mask_pix=None
close_oped_pix=None
label_pix=None
ws_dir ='./pic'
# Sobel 算子
sobel_Gx = [[-1, 0, 1],
            [-2, 0, 2],
            [-1, 0, 1]]
sobel_Gy = [[1, 2, 1],
            [0, 0, 0],
            [-1, -2, -1]]
op_sobel = [0, 0]
op_sobel[0] = sobel_Gx
op_sobel[1] = sobel_Gy

prewitt_Gx=[[-1,0,1],
            [-1,0,1],
            [-1,0,1]]
prewitt_Gy=[[1,1,1],
            [0,0,0],
            [-1,-1,-1]]
op_prewitt = [0,0]
op_prewitt[0]=prewitt_Gx
op_prewitt[1]=prewitt_Gy

laplas_Gx = [[0, 1, 0],
            [1, -4, 1],
            [0, 1, 0]]
laplas_Gy = [[0, 1, 0],
            [1, -4, 1],
            [0, 1, 0]]
# laplas_Gy = [[0, 1, 0],
#             [1, -4, 1],
#             [0, 1, 0]]
op_laplas = [0, 0]
op_laplas[0] = sobel_Gx
op_laplas[1] = sobel_Gy


def save_img_time(img,label):
    if not isinstance(label,str):
        print('label error')
        return
    t=time.asctime()
    t=t.split()[1:4]
    time_str=''
    for i in range(3):
        time_str+=t[i]
        if i < 2:
            time_str+='_'
    img=img.convert('L')
    global ws_dir
    img.save(ws_dir+'/'+label+'_'+time_str+'.jpg')


def open_raw_again():
    global raw_file_dir
    if raw_file_dir=="":
        print('reopen raw failed, please open image first')
        return
    img = Image.open(raw_file_dir)
    img.show()



def select_path():
    path_temp = askopenfile()
    file_dir = path_temp.name

    global raw_file_dir
    global raw_file_pix
    global cur_pix

    raw_file_dir=file_dir
    print(file_dir)
    img = Image.open(file_dir)
    img.show()
    raw_file_pix = np.array(img)
    cur_pix=raw_file_pix
    print('raw_file_shape',raw_file_pix.shape)
    # print(type(raw_file_pix[10,10]))

def sobel():
    ret = operator_func(op_sobel)
    ret_img = Image.fromarray(ret)
    ret_img.show()
    # ret_img.save('./1.png')
    # save_img_time(ret_img,'sobel')


def prewitt():
    ret = operator_func(op_prewitt)
    ret_img = Image.fromarray(ret)
    ret_img.show()
    # save_img_time(ret_img, 'prewitt')

def laplas():
    ret = operator_func(op_laplas)
    ret_img = Image.fromarray(ret)
    ret_img.show()
    # save_img_time(ret_img, 'prewitt')


# 使用算子进行边缘检测
@jit
def operator_func(listed_operator):
    global cur_pix
    pix = cur_pix.copy()
    if len(listed_operator) != 2:
        print('Operator number error!')
        return
    op_x = np.array(listed_operator[0])
    op_y = np.array(listed_operator[1])
    shape_img = pix.shape
    if op_x.shape!=op_y.shape:
        print('Operator Shape Error! Not same shape')
        return
    shape_filter = op_x.shape
    ret_x = np.zeros((shape_img[0]-shape_filter[0]+1,shape_img[1]-shape_filter[1]+1))
    ret_y = np.zeros_like(ret_x)
    ret = np.zeros_like(ret_x)
    for i in range(ret_x.shape[0]):
        for j in range(ret_x.shape[1]):
            for k in range(shape_filter[0]):
                for l in range(shape_filter[1]):
                    ret_x[i][j] += op_x[k,l]*pix[i+k][j+l]
                    ret_y[i][j] += op_y[k,l]*pix[i+k][j+l]
    for i in range(ret_x.shape[0]):
        for j in range(ret_x.shape[1]):
            ret[i,j] = math.sqrt(ret_x[i,j]**2 + ret_y[i,j]**2)
    return ret


def FFT():
    fft_pix = np.fft.fft2(raw_file_pix)
    fft_pix_abs = (np.abs(np.fft.fftshift(fft_pix)))/2000
    print(fft_pix)

    global fft_file_pix
    fft_file_pix = fft_pix

    fft_img = Image.fromarray(fft_pix_abs)
    fft_img = fft_img.convert('L')
    fft_img.show()
    save_img_time(fft_img, 'FFT')


def denoise():
    global fft_file_pix
    fft_pix = np.fft.fftshift(fft_file_pix)
    for i in range(fft_pix.shape[0]//2-5,fft_pix.shape[0]//2+6):
        for j in range(fft_pix.shape[0]//2-10,fft_pix.shape[0]//2-4):
            fft_pix[i,j]/=10
            fft_pix[i,j+15]/=10
    global ifft_file_pix
    ifft_file_pix=fft_pix

    ifft_img = np.abs(fft_pix)/2000
    ifft_img = Image.fromarray(ifft_img)
    ifft_img = ifft_img.convert('L')
    ifft_img.show()
    save_img_time(ifft_img, 'Denoise')


def IFFT():
    global ifft_file_pix
    ifft_pix = np.fft.ifftshift(ifft_file_pix)
    ifft_pix = np.fft.ifft2(ifft_pix)
    ifft_pix = ifft_pix.real
    ifft_img = Image.fromarray(ifft_pix)
    ifft_img.show()
    save_img_time(ifft_img, 'IFFT')


# @jit
def lsm():
    # (x,y)
    up=[[510,92],
        [381,398],
        [327,330],
        [121,312],
        [254,173],
        [69,140],
        [99,62]]
    up=np.mat(up)
    # (u,v)
    down=[[51,138],
          [384,37],
          [369,125],
          [480,289],
          [292,285],
          [386,440],
          [300,481]]
    down=np.mat(down)
    # info_up = str(up).replace('\n','')
    # info_down = str(down).replace('\n','')
    # tk.messagebox.showinfo('关键点坐标', info_up)
    A=[]
    # B0=np.zeros((6,1))
    # B1=B0.copy()
    for i in range(7):
        line = [1,down[i,0],down[i,1],down[i,0]**2,down[i,1]**2,down[i,0]*down[i,1]]
        A.append(line)
    A=np.mat(A)
    A_=[]
    for i in range(7):
        line = [1,up[i,0],up[i,1],up[i,0]**2,up[i,1]**2,up[i,0]*up[i,1]]
        A_.append(line)
    A_=np.mat(A_)
    B0=((A.T*A).I*A.T)*up[:,0]
    B1=((A.T*A).I*A.T)*up[:,1]
    print(B0)
    print(B1)

    B0_=((A_.T*A_).I*A_.T)*down[:,0]
    B1_=((A_.T*A_).I*A_.T)*down[:,1]
    print(B0_)
    print(B1_)

    global raw_file_pix
    pix=raw_file_pix.copy()
    max_i_ = 0
    max_j_ = 0
    table = []
    # for i in range(pix.shape[0]):
    #     for j in range(pix.shape[1]):
    #         a=[1,j,i,j**2,i**2,i*j]
    #         j_=int(round((a*B0)[0,0]))
    #         i_=int(round((a*B1)[0,0]))
    #         table.append((i,j,i_,j_))
    #         if i_>max_i_:
    #             max_i_=i_
    #         if j_>max_j_:
    #             max_j_=j_
    # print(max_i_,max_j_)
    # pix_=np.zeros((max_i_+1,max_j_+1,3),dtype='uint8')
    #
    # for item in table:
    #     pix_[item[2]][item[3]] = pix[item[0]][item[1]]
    pix_=np.zeros((pix.shape[0],pix.shape[1],3),dtype='uint8')
    for i in range(pix_.shape[0]):
        for j in range(pix_.shape[1]):
            a=[1,j,i,j**2,i**2,i*j]
            j_=int(round((a*B0_)[0,0]))
            i_=int(round((a*B1_)[0,0]))
            if i_>=pix.shape[0] or i_<0 or j_>=pix.shape[1] or j_<0:
                continue
            pix_[i,j]=pix[i_,j_]

    print(raw_file_pix.shape)
    print(pix_.shape)
    img_ = Image.fromarray(pix_)
    img_.show()


def digit_entry(function,info):
    def amp_get():
        amp_=entry_amp.get()
        amp = int(amp_)
        ask.destroy()
        function(amp)
    ask=tk.Tk()
    var_amp = tk.StringVar()
    tk.Label(ask,text=info).pack()
    entry_amp = tk.Entry(ask,textvariable=var_amp)
    entry_amp.pack()
    ok_button = tk.Button(ask,text='确定',command=amp_get).pack()
    ask.mainloop()


def nearest_neighboor_entry():
    digit_entry(nearest_neighboor,'请输入放大倍数')


@jit
def nearest_neighboor(amp):
    global raw_file_pix
    ret_pix = np.zeros((raw_file_pix.shape[0]*int(amp),raw_file_pix.shape[1]*int(amp),3),dtype='uint8')
    for i in range(ret_pix.shape[0]):
        for j in range(ret_pix.shape[1]):
            ret_pix[i,j] = raw_file_pix[round(i/amp)-1][round(j/amp)-1]
    img_amplify = Image.fromarray(ret_pix)
    img_amplify.show()


def double_linear_entry():
    digit_entry(double_linear,'请输入放大倍数')


@jit
def double_linear(amp):
    global raw_file_pix
    ret_pix = np.zeros((raw_file_pix.shape[0]*int(amp),raw_file_pix.shape[1]*int(amp),3),dtype='uint8')
    for i in range(ret_pix.shape[0]):
        for j in range(ret_pix.shape[1]):
            fraction1 = i/amp-int(i/amp)
            fraction2 = j/amp-int(j/amp)
            left = raw_file_pix[int(i/amp)-1][int(j/amp)-1]*(1-fraction2)+\
                   raw_file_pix[int(i/amp)][int(j/amp)-1]*(fraction2)
            right = raw_file_pix[int(i/amp)-1][int(j/amp)]*(1-fraction2)+\
                    raw_file_pix[int(i/amp)][int(j/amp)]*(fraction2)
            ret_pix[i,j] = left*(1-fraction1)+right*(fraction1)
    img_amplify = Image.fromarray(ret_pix)
    img_amplify.show()


def tri_conv_entry():
    digit_entry(tri_conv,'请输入放大倍数')


# 三次卷积插值的内部函数
@jit
def S(x):
    x=abs(x)
    if x >= 0 and x < 1:
        return 1 - 2 * x ** 2 + x ** 3
    elif x >= 1 and x < 2:
        return 4 - 8 * x + 5 * x ** 2 - x ** 3
    elif x >= 2:
        return 0


@jit
def tri_conv(amp):
    global raw_file_pix
    pix = raw_file_pix.copy()
    ret = np.zeros((int(pix.shape[0] * amp), int(pix.shape[1] * amp)),dtype='uint8')

    for i in range(ret.shape[0]):
        for j in range(ret.shape[1]):
            cor = (i / amp, j / amp)
            cor_int = (int(cor[0]), int(cor[1]))
            cor_frag = (cor[0] - cor_int[0], cor[1] - cor_int[1])
            u = cor_frag[0]
            v = cor_frag[1]

            if cor_int[0] - 1 >= 0 and cor_int[1] - 1 >= 0 and cor_int[0] + 2 <= pix.shape[0] - 1 and cor_int[1] + 2 <= \
                    pix.shape[1] - 1:
                B = pix[cor_int[0] - 1:cor_int[0] + 3, cor_int[1] - 1:cor_int[1] + 3]
                C = np.array((S(v + 1), S(v), S(v - 1), S(v - 2))).reshape((4, 1))
                A = np.array((S(u + 1), S(u), S(u - 1), S(u - 2)))
                _ = np.dot(B, C)
                ret[i, j] = np.dot(A, _)
            else:
                ret[i, j] = 0
    img_ = Image.fromarray(ret)
    img_.show()


def size_entry(function):
    def amp_get():
        amp_=entry_amp.get()
        size = int(amp_)
        ask.destroy()
        start = time.time()
        function(size)
        end=time.time()
        time_used = end-start
        print(time_used)
        info = '用时:'+str(time_used)+'秒'
        tk.messagebox.showinfo('用时',info)

    ask=tk.Tk()
    var_amp = tk.StringVar()
    tk.Label(ask,text='请输入模板边长').pack()
    entry_amp = tk.Entry(ask,textvariable=var_amp)
    entry_amp.pack()
    ok_button = tk.Button(ask,text='确定',command=amp_get).pack()
    ask.mainloop()


def aver_smooth_entry():
    size_entry(aver_smooth)


@jit
def aver_smooth(size):
    global raw_file_pix
    # size = 3
    pix = raw_file_pix.copy()
    for i in range(pix.shape[0]):
        for j in range(pix.shape[1]):
            block = pix[max(0,i-size//2):min(pix.shape[0]-1,i+size//2+1),
                    max(0,j-size//2):min(pix.shape[1]-1,j+size//2+1)]
            block_aver = round(block.mean())
            pix[i,j]=block_aver
    img_=Image.fromarray(pix)
    img_.show()


def mid_smooth_entry():
    size_entry(mid_smooth)


@jit
def mid_smooth(size):
    global raw_file_pix
    pix = raw_file_pix.copy()
    for i in range(pix.shape[0]):
        for j in range(pix.shape[1]):
            block = pix[max(0,i-size//2):min(pix.shape[0]-1,i+size//2+1),
                    max(0,j-size//2):min(pix.shape[1]-1,j+size//2+1)]
            # 注意flatten()和sort()返回值不一样
            block = block.flatten()
            block.sort()
            block_mid = block[block.shape[0]//2]
            pix[i,j]=block_mid
    img_=Image.fromarray(pix)
    img_.show()


@jit
def hist_equal():
    global raw_file_pix
    pix = raw_file_pix.copy()
    hist_dic = {}
    num_all_pix = pix.shape[0] * pix.shape[1]
    for i in range(pix.shape[0]):
        for j in range(pix.shape[1]):
            if str(pix[i,j]) not in hist_dic.keys():
                hist_dic[str(pix[i,j])]=1
            else:
                hist_dic[str(pix[i,j])]+=1
    for k in hist_dic.keys():
        hist_dic[k]=hist_dic[k]/num_all_pix

    hist_dic_acc = hist_dic.copy()
    for i in hist_dic_acc.keys():
        for j in hist_dic_acc.keys():
            if int(i)>=int(j):
                hist_dic_acc[i]+=hist_dic[j]
    for i in range(pix.shape[0]):
        for j in range(pix.shape[1]):
            gray = pix[i,j]
            if gray!=0:
                pix[i,j] = hist_dic_acc[str(gray)]*255.0
    img_=Image.fromarray(pix)
    img_.show()


def range_entry(function):
    def amp_get():
        low = entry_1.get()
        high = entry_2.get()
        low = int(low)
        high = int(high)
        ask.destroy()
        function(low, high)

    ask = tk.Tk()
    var_1 = tk.StringVar()
    var_2 = tk.StringVar()
    tk.Label(ask, text='请输入变换后灰度范围（0-255）').pack()
    entry_1 = tk.Entry(ask, textvariable=var_1)
    entry_1.pack()
    entry_2 = tk.Entry(ask, textvariable=var_2)
    entry_2.pack()
    ok_button = tk.Button(ask, text='确定', command=amp_get).pack()
    ask.mainloop()

def linear_stretch_entry():
    range_entry(linear_stretch)


@jit
def linear_stretch(low,high):
    global raw_file_pix
    pix = raw_file_pix.copy()
    for i in range(pix.shape[0]):
        for j in range(pix.shape[1]):
            pix[i,j] = pix[i,j]/255.0*(high-low)+low
    img_=Image.fromarray(pix)
    img_.show()


# 大津阈值
@jit
def otsu():
    global cur_pix
    pix = cur_pix.copy()
    var_max = 0
    # t为当前分割的灰度阈值，遍历从0到pix中的max灰度
    # r_0为小于t的像素个数，sum_0为像素灰度加和，_1为大于的，对应
    for t in range(255):
        # if t%3 != 0:
        #     continue
        r_0 = 0
        sum_0 = 0
        r_1 = 0
        sum_1 = 0
        pix_num=float(pix.size)
        for i in pix.flatten():
            if i<= t:
                r_0+=1
                sum_0+=i
            else:
                r_1+=1
                sum_1+=i
        # 如果没有元素（会被0除）跳下一个t
        if r_0==0 or r_1==0:
            continue
        aver_0 = sum_0/float(r_0)
        aver_1 = sum_1/float(r_1)
        r_0 = r_0/pix_num
        r_1 = r_1/pix_num
        var = r_0*r_1*(aver_0-aver_1)**2
        if var>var_max:
            var_max=var
            t_opt = t
    for i in range(pix.shape[0]):
        for j in range(pix.shape[1]):
            if pix[i,j]<=t_opt:
                pix[i,j]=0
            else:
                pix[i,j]=255
    img_=Image.fromarray(pix)
    otsu_save(pix)
    img_.show()


def otsu_save(pix):
    global cur_pix
    cur_pix=pix
    print('save done! cur_pix')

def rgb2gray():
    global raw_file_pix
    global cur_pix
    pix = raw_file_pix.copy()
    gray=Image.fromarray(pix)
    gray=gray.convert('L')
    gray_pix=np.asarray(gray)
    img_=Image.fromarray(gray_pix)
    img_.show()
    cur_pix=gray_pix


def close_op_entry():
    digit_entry(close_op,'请输入核的边长(推荐5)')


def close_op(k_size):
    global cur_pix
    pix = cur_pix.copy()
    kernal=cv2.getStructuringElement(cv2.MORPH_RECT,(k_size,k_size))
    img_closed=cv2.morphologyEx(pix,cv2.MORPH_CLOSE,kernal)
    img_=Image.fromarray(img_closed)
    img_.show()
    cur_pix=np.asarray(img_closed)
    global close_oped_pix
    close_oped_pix=cur_pix.copy()
    print('close_op done!')


# @jit
def region_grow():
    global cur_pix
    pix=cur_pix.copy()
    label=np.zeros_like(pix,dtype='int')
    stack=[]
    moves4=[(-1,0),(1,0),(0,-1),(0,1)]

    def is_legal_point(point):
        if 0<=point[0]<cur_pix.shape[0] and 0<=point[1]<cur_pix.shape[1]:
            return True
        return False

    class_counter=1
    for i in range(pix.shape[0]):
        for j in range(pix.shape[1]):
            if pix[i,j]<20 and label[i,j]==0:
                stack.append((i,j))
                while len(stack)!=0:
                    cur_point=stack.pop()
                    label[cur_point[0],cur_point[1]]=class_counter
                    for move in moves4:
                        new_point=[cur_point[i]+move[i] for i in range(len(cur_point))]
                        if is_legal_point(new_point):
                            if pix[new_point[0],new_point[1]]<250 and\
                                    label[new_point[0],new_point[1]]==0:
                                stack.append(new_point)
                class_counter+=1
                stack=[]
    area={}
    for i in range(1,class_counter):
        area[i]=0
    for i in range(label.shape[0]):
        for j in range(label.shape[1]):
            if label[i,j]!=0:
                area[label[i,j]]+=1
    print(area)
    num_dels=[]
    for key in area:
        if area[key]<500:
            num_dels.append(key)
    print(num_dels)

    # 若保留8个区域，则先在1-8号中，找到要删掉的，记为m
    for m in range(1,class_counter-len(num_dels)):
        if m in num_dels:
            # 再从后8-12位中，找不被删掉的，换成m号
            for n in range(class_counter-len(num_dels),class_counter):
                if n not in num_dels:
                    # 遍历所有元素，换标号
                    for i in range(label.shape[0]):
                        for j in range(label.shape[1]):
                            if label[i,j]==m:
                                label[i,j]=0
                            elif label[i,j]==n:
                                label[i,j]=m
    class_num_af=class_counter-len(num_dels)
    area={}
    for i in range(1,class_num_af):
        area[i]=0
    for i in range(label.shape[0]):
        for j in range(label.shape[1]):
            if 0<label[i,j]<class_num_af:
                area[label[i,j]]+=1
            else:
                label[i,j]=0
    print(area)
    # global mask_pix
    # mask_pix=label
    global label_pix
    label_pix=label

    masked_show_save(label)
    # 可视化标号结果
    label_show=label*30
    label_show=np.asarray(label_show,dtype='uint8')
    img_=Image.fromarray(label_show)
    img_.show()


def masked_show_save(pix):
    global mask_pix
    mask_pix=pix


def masked_show():
    global close_oped_pix
    global mask_pix
    global cur_pix
    pix=close_oped_pix.copy()
    mask=mask_pix.copy()
    for i in range(pix.shape[0]):
        for j in range(pix.shape[1]):
            if mask[i,j]<1:
                pix[i,j]=255
    img_=Image.fromarray(pix)
    cur_pix=pix
    img_.show()
    save_img_time(img_,'maskedShow')


def one_key_masked_show():
    rgb2gray()
    close_op(k_size=5)
    otsu()
    region_grow()
    masked_show()

@jit
def local_otsu():
    global cur_pix
    pix = cur_pix.copy()
    # pix=pix[0:100,600:700]
    var_max = 0
    # t为当前分割的灰度阈值，遍历从0到pix中的max灰度
    # r_0为小于t的像素个数，sum_0为像素灰度加和，_1为大于的，对应
    for t in range(255):
        # if t%3 != 0:
        #     continue
        r_0 = 0
        sum_0 = 0
        r_1 = 0
        sum_1 = 0
        pix_num=float(pix.size)
        for i in pix.flatten():
            # 除掉纯白的背景点
            if i<255:
                if i<= t:
                    r_0+=1
                    sum_0+=i
                else:
                    r_1+=1
                    sum_1+=i
        # 如果没有元素（会被0除）跳下一个t
        if r_0==0 or r_1==0:
            continue
        aver_0 = sum_0/float(r_0)
        aver_1 = sum_1/float(r_1)
        r_0 = r_0/pix_num
        r_1 = r_1/pix_num
        var = r_0*r_1*(aver_0-aver_1)**2
        if var>var_max:
            var_max=var
            t_opt = t
    for i in range(pix.shape[0]):
        for j in range(pix.shape[1]):
            if pix[i,j]<255:
                if pix[i,j]<=t_opt:
                    pix[i,j]=0
                else:
                    pix[i,j]=130
    img_=Image.fromarray(pix)
    otsu_save(pix)
    img_.show()

def area_ratio():
    global cur_pix
    global label_pix
    pix=cur_pix
    label=label_pix
    area_dict={}
    area_r={}
    for i in range(1,int(max(label.flatten()))+1):
        area_dict[i]=[0,0]
    for i in range(label.shape[0]):
        for j in range(label.shape[1]):
            if label[i,j]!=0:
                if pix[i,j]==0:
                    area_dict[label[i,j]][0]+=1
                elif pix[i,j]==130:
                    area_dict[label[i,j]][1]+=1
    print(area_dict)
    for i in range(1,len(area_dict)+1):
        area_r[i]=area_dict[i][0]/(area_dict[i][0]+area_dict[i][1])
    print(area_r)

def top_hat_valley():
    global cur_pix
    k_size=5
    thresh=15
    pix = cur_pix.copy()

    kernal=cv2.getStructuringElement(cv2.MORPH_RECT,(k_size,k_size))
    img_closed=cv2.morphologyEx(pix,cv2.MORPH_CLOSE,kernal)
    pix=np.array(pix,dtype='int64')
    img_closed=np.array(img_closed,dtype='int64')
    pix_=cur_pix-img_closed
    pix_=np.abs(pix_)
    pix_=np.array(pix_,dtype='uint8')
    bin_pix = np.array(pix_>15,dtype='uint8')*255
    img_=Image.fromarray(bin_pix)
    img_.show()
    cur_pix = bin_pix

def region_grow2():
    region_grow()
    kernel=np.array([[8, 8, 8, 8, 8, 8, 8, 8, 8],
                     [8, 4, 4, 4, 4, 4, 4, 4, 8],
                     [8, 4, 2, 2, 2, 2, 2, 4, 8],
                     [8, 4, 2, 1, 1, 1, 2, 4, 8],
                     [8, 4, 2, 1, 0, 1, 2, 4, 8],
                     [8, 4, 2, 1, 1, 1, 2, 4, 8],
                     [8, 4, 2, 2, 2, 2, 2, 4, 8],
                     [8, 4, 4, 4, 4, 4, 4, 4, 8],
                     [8, 8, 8, 8, 8, 8, 8, 8, 8]])
    # kernel=np.array([[8, 8, 8, 8, 8, 8, 8, 8, 8],
    #                  [8, 4, 4, 4, 4, 4, 4, 4, 8],
    #                  [8, 4, 0, 0, 0, 0, 0, 4, 8],
    #                  [8, 4, 0, 0, 0, 0, 0, 4, 8],
    #                  [8, 4, 0, 0, 0, 0, 0, 4, 8],
    #                  [8, 4, 0, 0, 0, 0, 0, 4, 8],
    #                  [8, 4, 0, 0, 0, 0, 0, 4, 8],
    #                  [8, 4, 4, 4, 4, 4, 4, 4, 8],
    #                  [8, 8, 8, 8, 8, 8, 8, 8, 8]])
    global raw_file_pix
    global label_pix
    pix_=np.array(raw_file_pix)
    epoch = 5
    for _ in range(epoch):
        for i in range(4,label_pix.shape[0]-4):
            for j in range(4,label_pix.shape[1]-4):
                if label_pix[i,j]==0:
                    for ch in range(3):
                        pix_[i, j-1, ch] = np.sum(pix_[i - 4:i + 5, j - 4:j + 5, ch] * kernel) / 392
                        pix_[i, j+0, ch] = np.sum(pix_[i - 4:i + 5, j - 4:j + 5, ch] * kernel) / 392
                        pix_[i, j+1, ch] = np.sum(pix_[i - 4:i + 5, j - 4:j + 5, ch] * kernel) / 392
        img_=Image.fromarray(pix_)
        img_.show()